<script setup lang="ts">
import { computed, watch, ref, unref } from 'vue'
import { Close, Download, Document, Upload, ArrowRight, ArrowLeft } from '@element-plus/icons-vue'
import { useBaseFileApi } from '@/api/base'
import { swapArrayElements } from '@/utils'
import type { BusinessUIFile } from '@/types/custom'
import { isImageFormat } from '@/utils/reg'
import { VxeUI } from 'vxe-pc-ui'

interface Props {
  title?: string
  disabled?: boolean
  hideTitle?: boolean
}

const modelValue = defineModel<BusinessUIFile[] | undefined>()

const props = defineProps<Props>()

const emit = defineEmits(['input'])

const { GetBaseFileDown } = useBaseFileApi()

const formFiles = ref<BusinessUIFile[]>([])

// 顶部工具栏-下载
const onDownload = (file: BusinessUIFile) => {
  if (file.id) {
    GetBaseFileDown(file.id).then((data: any) => {
      const objectUrl = URL.createObjectURL(data)
      let link = document.createElement('a')
      link.style.display = 'none'
      link.href = objectUrl
      link.setAttribute('download', file.fileName)
      document.body.appendChild(link)
      link.click()
      URL.revokeObjectURL(objectUrl) // 释放内存
    })
  }
}

/**
 * 删除
 * @param index
 */
const onDelete = (index: number) => {
  modelValue.value?.splice(index, 1)
}

const isIdentical = (v: BusinessUIFile, b: BusinessUIFile) => {
  return (v.uid && v.uid === b.uid) || (v.id && v.id === b.id)
}

/**
 * 排序
 * @param file
 * @param choice
 */
const handleSwitch = (file: BusinessUIFile, choice: -1 | 1) => {
  const files = unref(modelValue) || []
  const index = files.findIndex((f) => isIdentical(f, file))
  const idx = index + choice
  if (index >= 0 && files[idx]) swapArrayElements(files, index, idx)
}

const previewImage = (file: BusinessUIFile) => {
  const items = unref(modelValue) || []
  const urlList = items
    .filter((file: BusinessUIFile) => !file.raw && isImageFormat(file.fileName))
    .map((v) => v.path)
  VxeUI.previewImage({
    activeIndex: urlList.findIndex((f) => f === file.path),
    urlList
  })
}

watch(
  formFiles,
  (files) => {
    if (!modelValue.value) modelValue.value = []
    modelValue.value?.push(
      ...files.map((file) => {
        return {
          ...file,
          fileName: file.raw?.name || '',
          raw: file.raw
        }
      })
    )
    formFiles.value.splice(0)
  },
  {
    immediate: true
  }
)

watch(
  modelValue,
  (files) => {
    const list = files || []
    list.sort((a, b) => {
      return (a.idx || 0) - (b.idx || 0)
    })
  },
  {
    immediate: true
  }
)

const isData = computed(() => {
  return !props.disabled || !!modelValue.value?.length
})
</script>

<template>
  <div v-if="isData" class="border-default base-radius">
    <div
      class="flex align-center justify-between border-solid title color-info"
      style="padding: 3px 5px"
      v-if="!hideTitle"
    >
      <div class="flex align-center">
        <el-icon>
          <Document />
        </el-icon>
        <span class="font14 ml5">{{ title || '附件列表' }}</span>
      </div>
      <div>
        <el-upload
          v-model:file-list="formFiles"
          :show-file-list="false"
          :auto-upload="false"
          multiple
          v-if="!disabled"
          class="flex align-center"
        >
          <template #trigger>
            <el-button type="primary" :icon="Upload" plain>上传附件</el-button>
          </template>
        </el-upload>
      </div>
    </div>
    <el-empty
      v-if="!modelValue?.length"
      :image-size="30"
      :description="`暂无${title}`"
      class="pa5"
    />
    <el-row :gutter="5" class="px5 pb5">
      <el-col
        v-for="(file, index) in modelValue"
        :key="index"
        :xs="24"
        :sm="12"
        :md="12"
        :lg="12"
        :xl="12"
      >
        <div class="flex mt5 border-dotted pa5" style="min-height: 62px">
          <vxe-image
            v-if="isImageFormat(file.fileName)"
            :src="file.path"
            :height="50"
            :show-preview="false"
            @click="previewImage(file)"
          />
          <span class="mx5">{{ index + 1 }}.</span>
          <div class="flex-grow">
            <div class="flex">
              <span v-if="!file.id" class="mr5 color-danger">新</span>
              <span>{{ file.fileName }}</span>
            </div>
            <div class="color-info font12 mt5">
              上传时间：{{ file.createdOnString || '待上传' }}（{{ file.uploadUserName || '- -' }}）
            </div>
          </div>
          <el-icon
            v-if="!disabled"
            size="16"
            @click="handleSwitch(file, -1)"
            class="ml5 cursor-pointer"
          >
            <ArrowLeft />
          </el-icon>
          <el-icon
            v-if="!disabled"
            size="16"
            @click="handleSwitch(file, 1)"
            class="ml5 cursor-pointer"
          >
            <ArrowRight />
          </el-icon>
          <el-icon
            v-if="file.id"
            size="16"
            @click="onDownload(file)"
            class="ml5 mr2 cursor-pointer"
          >
            <Download />
          </el-icon>
          <el-icon
            v-if="!disabled"
            size="18"
            @click="onDelete(index)"
            class="ml5 cursor-pointer color-danger"
          >
            <Close />
          </el-icon>
          <!--          <el-button-->
          <!--            size="small"-->
          <!--            circle-->
          <!--            :icon="Download"-->
          <!--            @click="onDownload(file)"-->
          <!--            v-if="file.id"-->
          <!--          />-->
          <!--          <el-button-->
          <!--            size="small"-->
          <!--            circle-->
          <!--            plain-->
          <!--            :icon="Close"-->
          <!--            type="danger"-->
          <!--            @click="onDelete(index)"-->
          <!--            v-if="!disabled"-->
          <!--            class="mr3"-->
          <!--          />-->
        </div>
      </el-col>
    </el-row>
  </div>
</template>
<style scoped>
.title {
  background-color: var(--el-fill-color-light);
}
</style>
